﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Outlook.WorkItems.Extension.Managers.TeamBuildManager;
using System.Xml.Linq;

namespace Outlook.WorkItems.Extension.Manager.TeamBuildManager
{
    public class TeamBuildLinksManager
    {
        /// <summary>
        /// File Path that contains Link Information between MAPIFolder and Team Builds
        /// </summary>
        private static readonly string filePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\OWIPlugin\\BuildLinks.owi";
        /// <summary>
        /// Dictionary of Team Project Link
        /// </summary>
        private static Dictionary<string, BuildCalendarLink> buildLinks;


        /// <summary>
        /// Initialize list of Team Project Links
        /// </summary>
        static TeamBuildLinksManager()
        {
            buildLinks = new Dictionary<string, BuildCalendarLink>();

            if (File.Exists(filePath))
            {
                var xdoc = XDocument.Load("file:///" + filePath);
                foreach (var item in xdoc.Root.Elements("BuildLink"))
                {
                    var tpl = new BuildCalendarLink()
                    {
                        FolderEntryID = item.Attribute("entryId").Value,
                        FolderStoreID = item.Attribute("storeId").Value,
                        TeamProjectName = item.Element("LinkTFS").Attribute("teamProjectName").Value,
                        TeamServerName = item.Element("LinkTFS").Attribute("teamServerName").Value,
                        TeamServerUri = item.Element("LinkTFS").Attribute("teamServerUri").Value
                    };
                    if (item.Element("LinkTFS").Elements().Any(xelt => xelt.Name == "SynchronizeBuildAction"))
                    {
                        tpl.SynchronizeBuildAction = new SynchronizeBuildAction();
                        tpl.SynchronizeBuildAction.DeserializeAction(item.Element("LinkTFS").Element("SynchronizeBuildAction"));
                    }

                    buildLinks.Add(tpl.FolderEntryID, tpl);
                }
            }
        }

        /// <summary>
        /// Create and Add specified Team Project Link
        /// </summary>
        /// <param name="entryId">MAPIFolder EntryId</param>
        /// <param name="storeId">MAPIFolder StoreId</param>
        /// <param name="teamServer">Team Server Name</param>
        /// <param name="teamServerUri"></param>
        /// <param name="teamProject">Team Project Name</param>
        /// <param name="synchronizeBuildAction"></param>
        public static void AddBuildLink(string entryId, string storeId, string teamServer, string teamServerUri, string teamProject, SynchronizeBuildAction synchronizeBuildAction)
        {
            var folderPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "OWIPlugin");
            if (Directory.Exists(folderPath) == false)
            {
                Directory.CreateDirectory(folderPath);
            }
            BuildCalendarLink tpl = null;
            if (ContainsBuildCalendarLink(entryId))
                tpl = GetBuildLink(entryId);
            else
            {
                tpl = new BuildCalendarLink() { FolderEntryID = entryId };
                buildLinks.Add(tpl.FolderEntryID, tpl);
            }

            tpl.FolderStoreID = storeId;
            tpl.TeamProjectName = teamProject;
            tpl.TeamServerName = teamServer;
            tpl.TeamServerUri = teamServerUri;
            tpl.SynchronizeBuildAction = synchronizeBuildAction;

            XDocument xdoc = null;
            if (File.Exists(filePath))
            {
                xdoc = XDocument.Load("file:///" + filePath);

                var root = (from xelt in xdoc.Root.Elements()
                            where xelt.Attribute("entryId").Value == entryId
                            select xelt).FirstOrDefault();
                if (root != null)
                {
                    root.Remove();
                }
            }
            else
            {
                xdoc = new XDocument(new XElement("BuildLinks"));
            }

            var elt = new XElement("BuildLink",
                                                new XAttribute("entryId", entryId),
                                                new XAttribute("storeId", storeId),
                                                new XElement("LinkTFS",
                                                    new XAttribute("teamServerName", teamServer),
                                                    new XAttribute("teamProjectName", teamProject),
                                                    new XAttribute("teamServerUri", teamServerUri)));

            if (synchronizeBuildAction != null)
            {
                elt.Element("LinkTFS").Add(synchronizeBuildAction.SerializeAction());
            }
            xdoc.Root.Add(elt);
            xdoc.Save(filePath);
        }

        public static bool ContainsBuildCalendarLink(string entryId)
        {
            return buildLinks.ContainsKey(entryId);
        }

        /// <summary>
        /// Return the Team Project Link with specified MAPIFolder entryId 
        /// </summary>
        /// <param name="entryId"></param>
        /// <returns></returns>
        public static BuildCalendarLink GetBuildLink(string entryId)
        {
            if (ContainsBuildCalendarLink(entryId) == false)
                throw new ApplicationException("No Build Calendar Link exist for this MAPIFolder");

            return buildLinks[entryId];
        }

        /// <summary>
        /// Return list of all configured Builds Link 
        /// </summary>
        /// <returns></returns>
        public static List<BuildCalendarLink> GetAllBuildCalendarLink()
        {
            return buildLinks.Values.ToList();
        }

        /// <summary>
        /// Remove the Team Project Link of a MAPIFolder EntryId
        /// </summary>
        /// <param name="entryId">MAPIFolder identity</param>
        public static void RemoveProjectLink(string entryId)
        {
            if (ContainsBuildCalendarLink(entryId) == false)
                return;
            buildLinks.Remove(entryId);

            if (!File.Exists(filePath))
                return;

            var xdoc = XDocument.Load("file:///" + filePath);
            var item = (from elt in xdoc.Root.Elements()
                        where elt.Attribute("entryId").Value == entryId
                        select elt).FirstOrDefault();

            if (item != null)
                item.Remove();

            xdoc.Save(filePath);
        }
    }
}
